package com.ithuameng.admin.app.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ithuameng.admin.app.system.dao.RoleMapper;
import com.ithuameng.admin.app.system.model.Role;
import com.ithuameng.admin.app.system.model.RoleMenu;
import com.ithuameng.admin.app.system.model.admin.qo.RoleQo;
import com.ithuameng.admin.app.system.model.admin.vo.UserRoleAuthVo;
import com.ithuameng.admin.app.system.service.IRoleMenuService;
import com.ithuameng.admin.app.system.service.IRoleService;
import com.ithuameng.admin.app.system.service.IUserRoleService;
import com.ithuameng.admin.constants.CommonConstants;
import com.ithuameng.admin.enums.CommonError;
import com.ithuameng.admin.enums.YesNo;
import com.ithuameng.admin.exception.AdminException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * Role service implementation
 *
 * @author ithuameng
 */
@Transactional
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Resource
    private IRoleMenuService roleMenuService;

    @Resource
    private IUserRoleService userRoleService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public IPage<Role> listRole(Page<Role> page, RoleQo roleQo) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        if (roleQo != null) {
            if (StringUtils.isNotBlank(roleQo.getName())) {
                queryWrapper.like(Role.NAME, roleQo.getName());
            }

            if (StringUtils.isNotBlank(roleQo.getRoleKey())) {
                queryWrapper.like(Role.ROLE_KEY, roleQo.getRoleKey());
            }

            if (roleQo.getStatus() != null) {
                queryWrapper.eq(Role.STATUS, roleQo.getStatus());
            }
        }
        return super.page(page, queryWrapper);
    }

    @Override
    public List<UserRoleAuthVo> selectRolesByUserId(Long userId) {
        List<Role> userRoles = super.baseMapper.selectRolePermissionByUserId(userId);
        List<UserRoleAuthVo> userRoleWithAuths = new ArrayList<>();
        List<Role> roles = super.list();
        for (Role role : roles) {
            UserRoleAuthVo userRoleAuthVo = new UserRoleAuthVo();
            BeanUtils.copyProperties(role, userRoleAuthVo);
            for (Role userRole : userRoles) {
                if (role.getId().longValue() == userRole.getId().longValue()) {
                    userRoleAuthVo.setFlag(true);
                    break;
                }
            }
            userRoleWithAuths.add(userRoleAuthVo);
        }
        return userRoleWithAuths;
    }

    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        List<Role> perms = super.baseMapper.selectRolePermissionByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (Role perm : perms) {
            if (perm != null) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public void checkRoleDataScope(Long roleId) {
//		if (!SysUser.isAdmin(SecurityUtils.getUserId()))
//        {
//            SysRole role = new SysRole();
//            role.setRoleId(roleId);
//            List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
//            if (StringUtils.isEmpty(roles))
//            {
//                throw new ServiceException("没有权限访问角色数据！");
//            }
//        }
    }

    @Override
    public boolean checkRoleNameUnique(String roleName, Long execuldeId) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Role.NAME, roleName);
        if (execuldeId != null) {
            queryWrapper.ne(Role.ID, execuldeId);
        }
        return super.count(queryWrapper) == 0;
    }

    @Override
    public boolean checkRoleKeyUnique(String roleKey, Long execuldeId) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Role.ROLE_KEY, roleKey);
        if (execuldeId != null) {
            queryWrapper.ne(Role.ID, execuldeId);
        }
        return super.count(queryWrapper) == 0;
    }

    @Override
    public void saveRoleWithMenus(Role role, Long[] menuIds) {
        super.save(role);
        if (menuIds == null) {
            return;
        }
        Long roleId = role.getId();
        List<RoleMenu> list = new ArrayList<RoleMenu>();
        for (Long menuId : menuIds) {
            RoleMenu roleMenu = new RoleMenu(roleId, menuId);
            list.add(roleMenu);
        }
        if (list.size() > 0) {
            roleMenuService.saveBatch(list);
        }
    }

    @Override
    public void updateRoleWithMenus(Role role, Long[] menuIds) {
        Long roleId = role.getId();
        super.updateById(role);
        // 删除旧的
        QueryWrapper<RoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(RoleMenu.ROLE_ID, roleId);
        roleMenuService.remove(queryWrapper);
        // 保存新的
        List<RoleMenu> list = new ArrayList<RoleMenu>();
        for (Long menuId : menuIds) {
            RoleMenu roleMenu = new RoleMenu(roleId, menuId);
            list.add(roleMenu);
        }
        if (list.size() > 0) {
            roleMenuService.saveBatch(list);
        }
        List<Long> userIds = userRoleService.listUserByRoleId(roleId);
        userIds.forEach(uid -> {
            String key = CommonConstants.PERMESSION_PREFIX + Long.toString(uid);
            if (stringRedisTemplate.hasKey(key)) {
                stringRedisTemplate.delete(key);
            }
        });
    }

    @Override
    public void deleteRoleByIds(Long[] roleIds) {
        if (roleIds == null) {
            return;
        }
        for (Long roleId : roleIds) {
            Role role = super.getById(roleId);
            int roleMenuCounts = roleMenuService.countRoleMenus(roleId);
            if (roleMenuCounts > 0) {
                throw new AdminException(CommonError.BIZ_ERR, String.format("%1$s已分配菜单,不能删除", role.getName()));
            }
        }
        roleMenuService.deleteByRoleId(roleIds);
        super.removeByIds(Arrays.asList(roleIds));
        for (int i = 0; i < roleIds.length; i++) {
            List<Long> userIds = userRoleService.listUserByRoleId(roleIds[i]);
            userIds.forEach(uid -> {
                String key = CommonConstants.PERMESSION_PREFIX + Long.toString(uid);
                if (stringRedisTemplate.hasKey(key)) {
                    stringRedisTemplate.delete(key);
                }
            });
        }
    }

    @Override
    public void updateRoleStatus(Long roleId, YesNo status) {
        Role role = new Role();
        role.setId(roleId);
        role.setStatus(status);
        super.updateById(role);
    }
}
